<template>
	<view class="page">
		<view class="row">
			<text>扫描状态：</text>
			<text>{{msg}}</text>
		</view>
    <view class="row">
      <button class="button" size="mini" @click="startScan()">开始扫描</button>
      <button class="button" @click="stopScan()" size="mini">停止扫描</button>
      <button class="button" size="mini" @click="getAllScan()">获取所有</button>
      <button class="button" size="mini" @click="getConnected()">获取已连</button>
      <button class="button" size="mini" @click="getStatus()">获取状态</button>
    </view>
    <view class="row">
      <text>日志</text>
    </view>
    <scroll-view class="border list" scroll-y="true" :scroll-into-view="toBottom" :style="{width:'93vw',height:'25vh'}">
      <text class="log" selectable="true">{{log}}</text>
      <view id="bottomId" class="log-bottom"></view>
    </scroll-view>
    <view class="row">
      <text>设备列表</text>
      <text>({{deviceList.length}})</text>
    </view>
		<scroll-view class="border list" scroll-y="true" :style="{width:'93vw',height:'38vh'}">
			<view v-for="(item,index) in deviceList" :key="index" class="list-item">
				<view class="column">
				  <text class="text">{{item.name}}</text>
				  <view class="row">
            <text class="text">{{item.advertisServiceUUIDs.length}}</text>
            <text class="text">个主服务</text>
            <text class="text">信号强度</text>
            <text class="text">{{item.RSSI}}</text>
            <button v-if="!item.connected" size="mini" class="button" @click="toConnect(item.deviceId)">连接</button>
            <button v-if="item.connected" size="mini" @click="disConnect(item.deviceId)">断开连接</button>
				  </view>
				</view>
			  </view>
		</scroll-view>
	</view>
</template>

<script>
	const ble = uni.requireNativePlugin('sand-plugin-bluetooth');
	var _this;
	export default {
		data() {
			return {
				title: 'Hello',
				msg:'还未开始',
        log:'',
				deviceList:[],
				deviceMap:{},
        toBottom:''
			}
		},
		onLoad() {
			_this=this;
			this.initListener();
		},
		methods: {
			initListener(){
				//适配器监听
				ble.onBluetoothAdapterStateChange({},(res)=>{
					console.log('适配器状态变化',res);
          _this.msg=res.message;
          _this.addLog(res.message);
				});
				//发现设备监听
				ble.onBluetoothDeviceFound({},(res)=>{
					console.log('发现了设备',res);
					if(res.status=='2500'){
						let devices=JSON.parse(res.devices);
						_this.addFindDevice(devices);
					}
				});
        //监听设备连接监听
        ble.onBLEConnectionStateChange({},(res)=>{
          let deviceId=res.deviceId;
          let connected=res.connected;
          let list=[..._this.deviceList];
          let dev=list[_this.deviceMap[deviceId]];
          dev.connected=connected;
          _this.deviceList=list;
          _this.addLog(dev.name+"连接状态="+connected);
          console.log(dev.name+"连接状态="+connected);
          //连接成功，获取服务和订阅特征
          if(connected==true){
            _this.notify(deviceId);
          }
        });
        //监听特征数据
        ble.onBLECharacteristicValueChange({},(res)=>{
          _this.addLog('十六进制值:'+res.value);
          console.log('十六进制值:'+res.value);
          let value=res.value;
          _this.addLog('解析后的值:'+JSON.stringify(_this.hex2Bytes(value)));
          console.log('解析后的值:'+JSON.stringify(_this.hex2Bytes(value)));
        });
				//打开适配器
				ble.openBluetoothAdapter({},(res)=>{
					console.log(res);
					_this.msg=res.message;
          _this.addLog(res.message);
				});
				
			},
      //启动扫描
      startScan(){
        ble.startBluetoothDevicesDiscovery({},(res)=>{
          _this.msg=res.message;
        });
      },
      //停止扫描
      stopScan(){
        ble.stopBluetoothDevicesDiscovery({},(res)=>{
          _this.msg=res.message;
          _this.addLog(res.message);
        });
      },
      //连接设备
      toConnect(deviceId){
        //停止扫描
        ble.stopBluetoothDevicesDiscovery({},(res)=>{
          _this.addLog(res.message);
        });
        //开始连接
        ble.createBLEConnection({deviceId:deviceId},(res)=>{
          _this.addLog(res.message);
          //加入自动重连
          ble.addAutoReconnect({deviceId:deviceId},(res2)=>{
            _this.addLog(res2.message);
          });
        });
      },
      //断开连接
      disConnect(deviceId){
        ble.removeAutoReconnect({deviceId:deviceId},(res)=>{
          _this.addLog(res.message);
          ble.closeBLEConnection({deviceId:deviceId},(res2)=>{
            _this.addLog(res2.message);
          });
        });
        
      },
      //刷新服务和订阅特征
      notify(deviceId){
        let timeout=0;
        setTimeout(()=>{
          //获取服务列表
          ble.getBLEDeviceServices({deviceId:deviceId},(res)=>{
            console.log(res);
            if(res.status=='2500'){
              let services=JSON.parse(res.services);
              _this.addLog(res.message+","+res.services);
              //由于是异步方法，采用递归进行遍历
              var diguiServices=function(serArr,index){
                ble.getBLEDeviceCharacteristics({
                  deviceId: deviceId,
                  serviceId: serArr[index].uuid
                  },(res2)=>{
                    _this.addLog(res2.message+","+res2.characteristics);
                    let characteristics=JSON.parse(res2.characteristics);
                    //订阅设备特征
                    if(serArr[index].uuid.indexOf('1905')>=0){
                      for (let j = 0; j < characteristics.length; j++) {
                        let characteristic=characteristics[j];
                        if(characteristic.properties.notify==true){
                          ble.notifyBLECharacteristicValueChange({
                            deviceId:deviceId,
                            serviceId:serArr[index].uuid,
                            characteristicId:characteristic.uuid
                          },(res3)=>{
                            _this.addLog(res3.message);
                          });
                        }
                        //读特征值
                        if(characteristic.properties.read==true){
                          ble.readBLECharacteristicValue({
                            deviceId:deviceId,
                            serviceId:serArr[index].uuid,
                            characteristicId:characteristic.uuid
                          },(res3)=>{
                            _this.addLog(res3.message);
                          });
                        }
                        //写一个值过去
                        if(characteristic.properties.write==true){
                          ble.writeBLECharacteristicValue({
                            deviceId:deviceId,
                            serviceId:serArr[index].uuid,
                            characteristicId:characteristic.uuid,
                            value:"01"//十六进制数据
                          },(res3)=>{
                            _this.addLog(res3.message);
                          });
                        }
                      }
                    }
                    
                    
                    let index2=index+1;
                    if(index2>=serArr.length){
                      return;
                    }else{
                      // console.log("递归下一个服务的特征值");
                      diguiServices(serArr,index2);
                    }
                  });
              };
              //开始遍历服务
              diguiServices(services,0);
            }else{
              _this.addLog(res.message);
            }
          });
        },timeout);
      },
      getAllScan(){
        //获取已经扫描到的所有设备
        ble.getBluetoothDevices({},(res)=>{
          _this.addLog('获取所有:'+res.devices);
          let arr=JSON.parse(res.devices);
          _this.addFindDevice(arr);
          for(let i=0; i<arr.length; i++){
            let dev=arr[i];
            if(dev.restore){
              _this.addLog('准备恢复这台设备'+dev.name);
              _this.toConnect(dev.deviceId);
            }
          }
        });
      },
      getConnected(){
        //获取已连接的所有设备
        ble.getConnectedBluetoothDevices({},(res)=>{
          _this.addLog('获取已连:'+res.devices);
        });
      },
      getStatus(){
        //获取当前适配器状态
        ble.getBluetoothAdapterState({},(res)=>{
          _this.addLog('获取状态:'+JSON.stringify(res));
        });
      },
      addLog(msg){
        _this.log=_this.log+new Date().toLocaleString()+":"+msg+"\r\n";
        _this.toBottom='';
        setTimeout(()=>{
          _this.toBottom="bottomId";
        },200);
      },
      addFindDevice(devices){
        let list=[..._this.deviceList];
        for(let i=0; i<devices.length ; i++){
          let dev=devices[i];
          //去重
          if(_this.deviceMap[dev.deviceId]>=0){
            let index=_this.deviceMap[dev.deviceId];
            //更新
            list.splice(index,1,dev);
          }else{
            //新增
            list.push(dev);
            _this.deviceMap[dev.deviceId]=list.length-1;
          }
        }
        _this.deviceList=list;
      },
      //十六进制字符串转数组
      hex2Bytes(hexStr){
        var pos = 0;
        var len = hexStr.length;
        if (len % 2 != 0) {
          return null;
        }
        len /= 2;
        var hexA = new Array();
        for (var i = 0; i < len; i++) {
          var s = hexStr.substr(pos, 2);
          var v = parseInt(s, 16);
          hexA.push(v);
          pos += 2;
        }
        return hexA;
      }
		}
	}
</script>

<style lang="scss">
.page{
  width: 100vw;
}
.row{
  display: flex;
  flex-direction: row;
  align-content: flex-start;
  align-items: flex-start;
  margin: 15px 10px;
  padding: 5px;
  .button{
    width: 100px;
    font-size: 11px;
    background-color: #003366;
    color: white;
  }
}
.border{
  border: solid 1px gray;
}
.list{
  padding-left: 3vw;
  padding-right: 3vw;
  padding-top: 3vw;
  .list-item{
    background-color: #f8f8f8;
    border: solid 1px darkgray;
    box-shadow: 1px 1px 3px;
    margin-bottom: 3vw;
    .text{
      height: 30px;
      line-height: 30px;
      margin-left: 5px;
    }
    .row{
      margin: 3px 10px !important;
      padding:0 !important;
    }
  }
}
.log{
 width: 87vw;
 font-size: 13px;
 color: #003366;
 .log-bottom{
   height: 10vw;
 }
}
</style>
